package com.mockapi.service;

import cn.hutool.core.util.StrUtil;
import com.fasterxml.jackson.core.type.TypeReference;
import com.mockapi.entity.ApiLog;
import com.mockapi.entity.ResponseTemplate;
import com.mockapi.entity.Route;
import com.mockapi.util.FreeMarkerUtil;
import com.mockapi.util.JsonUtils;
import jakarta.servlet.http.HttpServletRequest;
import lombok.Builder;
import lombok.Data;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import java.io.BufferedReader;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;

/**
 * Mock服务
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class MockService {

    private final RouteService routeService;
    private final ResponseTemplateService responseTemplateService;
    private final ApiLogService apiLogService;
    private final EventService eventService;

    /**
     * 处理Mock请求
     */
    public MockResponse handleRequest(HttpServletRequest request) {
        long startTime = System.currentTimeMillis();
        
        // 获取请求信息
        String requestPath = request.getRequestURI();
        String requestMethod = request.getMethod();
        String requestBody = getRequestBody(request);
        Map<String, String> requestHeaders = getRequestHeaders(request);
        Map<String, String> requestParams = getRequestParams(request);
        String ipAddress = getClientIpAddress(request);
        String userAgent = request.getHeader("User-Agent");

        // 查找匹配的路由
        Route route = routeService.findMatchingRoute(requestPath, requestMethod);

        if (route == null) {
            // 没有找到匹配的路由，返回404
            MockResponse notFoundResponse = createNotFoundResponse();

            // 记录404日志
            saveApiLog(null, requestPath, requestMethod, requestHeaders,
                    requestParams, requestBody, notFoundResponse.getStatusCode(),
                    notFoundResponse.getHeaders(), notFoundResponse.getBody(),
                    (int) (System.currentTimeMillis() - startTime), ipAddress, userAgent);

            return notFoundResponse;
        }
        try {
            // 获取响应模板
            ResponseTemplate template = null;
            if (route.getTemplateId() != null) {
                template = responseTemplateService.getById(route.getTemplateId());
            }

            // 构建请求数据模型
            Map<String, Object> requestData = buildRequestData(requestPath, requestMethod, 
                    requestHeaders, requestParams, requestBody);

            // 渲染响应内容
            String responseBody = "";
            if (template != null) {
                responseBody = FreeMarkerUtil.renderTemplate(template.getTemplateContent(), requestData);
            }

            // 模拟延迟
            if (route.getDelayMs() > 0) {
                try {
                    Thread.sleep(route.getDelayMs());
                } catch (InterruptedException e) {
                    Thread.currentThread().interrupt();
                }
            }

            // 计算响应时间
            long responseTime = System.currentTimeMillis() - startTime;

            // 触发Mock调用后的事件
            eventService.triggerMockCallEvents(route.getId(), requestMethod, requestData);

            // 处理响应头
            Map<String, String> responseHeaders = new HashMap<>();
            if (template != null && StrUtil.isNotBlank(template.getHeaders())) {
                String renderHeaders = FreeMarkerUtil.renderTemplate(template.getHeaders(), requestData);
                Map<String, String> templateHeaders = JsonUtils.parseObject(renderHeaders, new TypeReference<>() {});
                // 使用FreeMarker渲染每个header值
                responseHeaders.putAll(templateHeaders);
            }

            // 记录日志
            saveApiLog(route.getId(), requestPath, requestMethod, requestHeaders,
                    requestParams, requestBody, route.getStatusCode(), responseHeaders,
                    responseBody, (int) responseTime, ipAddress, userAgent);

            // 返回响应
            return MockResponse.builder()
                    .statusCode(route.getStatusCode())
                    .contentType(template != null ? template.getContentType() : "application/json")
                    .body(responseBody)
                    .headers(responseHeaders)
                    .build();

        } catch (Exception e) {
            log.error("处理Mock请求失败", e);
            MockResponse errorResponse = createErrorResponse();
            
            // 记录错误日志
            saveApiLog(route.getId(), requestPath, requestMethod, requestHeaders,
                    requestParams, requestBody, errorResponse.getStatusCode(), 
                    errorResponse.getHeaders(), errorResponse.getBody(), 
                    (int) (System.currentTimeMillis() - startTime), ipAddress, userAgent);
            
            return errorResponse;
        }
    }

    /**
     * 获取请求体
     */
    private String getRequestBody(HttpServletRequest request) {
        try {
            BufferedReader reader = request.getReader();
            StringBuilder sb = new StringBuilder();
            String line;
            while ((line = reader.readLine()) != null) {
                sb.append(line);
            }
            return sb.toString();
        } catch (IOException e) {
            log.error("读取请求体失败", e);
            return "";
        }
    }

    /**
     * 获取请求头
     */
    private Map<String, String> getRequestHeaders(HttpServletRequest request) {
        Map<String, String> headers = new HashMap<>();
        java.util.Enumeration<String> headerNames = request.getHeaderNames();
        while (headerNames.hasMoreElements()) {
            String name = headerNames.nextElement();
            headers.put(name, request.getHeader(name));
        }
        return headers;
    }

    /**
     * 获取请求参数
     */
    private Map<String, String> getRequestParams(HttpServletRequest request) {
        Map<String, String> params = new HashMap<>();
        java.util.Enumeration<String> paramNames = request.getParameterNames();
        while (paramNames.hasMoreElements()) {
            String name = paramNames.nextElement();
            params.put(name, request.getParameter(name));
        }
        return params;
    }

    /**
     * 获取客户端IP地址
     */
    private String getClientIpAddress(HttpServletRequest request) {
        String xForwardedFor = request.getHeader("X-Forwarded-For");
        if (xForwardedFor != null && !xForwardedFor.isEmpty()) {
            return xForwardedFor.split(",")[0].trim();
        }
        
        String xRealIp = request.getHeader("X-Real-IP");
        if (xRealIp != null && !xRealIp.isEmpty()) {
            return xRealIp;
        }
        
        return request.getRemoteAddr();
    }

    /**
     * 构建请求数据模型
     */
    private Map<String, Object> buildRequestData(String path, String method, 
                                                Map<String, String> headers, 
                                                Map<String, String> params, 
                                                String body) {
        Map<String, Object> requestData = new HashMap<>();
        requestData.put("path", path);
        requestData.put("method", method);
        requestData.put("headers", headers);
        requestData.put("params", params);
        
        // 尝试解析JSON请求体
        if (body != null && !body.isEmpty()) {
            Map<String, Object> jsonBody = JsonUtils.parseObject(body, new TypeReference<>() {
            });
            requestData.put("body", jsonBody);
        }
        
        return requestData;
    }

    /**
     * 保存API日志
     */
    private void saveApiLog(Long routeId, String requestPath, String requestMethod,
                           Map<String, String> requestHeaders, Map<String, String> requestParams,
                           String requestBody, Integer responseStatus, Map<String, String> responseHeaders,
                           String responseBody, Integer responseTimeMs, String ipAddress, String userAgent) {
        ApiLog apiLog = new ApiLog();
        apiLog.setRouteId(routeId);
        apiLog.setRequestPath(requestPath);
        apiLog.setRequestMethod(requestMethod);
        apiLog.setRequestHeaders(JsonUtils.toJsonString(requestHeaders));
        apiLog.setRequestParams(JsonUtils.toJsonString(requestParams));
        apiLog.setRequestBody(requestBody);
        apiLog.setResponseStatus(responseStatus);
        apiLog.setResponseHeaders(JsonUtils.toJsonString(responseHeaders));
        apiLog.setResponseBody(responseBody);
        apiLog.setResponseTimeMs(responseTimeMs);
        apiLog.setIpAddress(ipAddress);
        apiLog.setUserAgent(userAgent);

        apiLogService.save(apiLog);
    }

    /**
     * 创建404响应
     */
    private MockResponse createNotFoundResponse() {
        return MockResponse.builder()
                .statusCode(404)
                .contentType("application/json")
                .body("{\"error\":\"Not Found\",\"message\":\"No matching route found\"}")
                .build();
    }

    /**
     * 创建错误响应
     */
    private MockResponse createErrorResponse() {
        return MockResponse.builder()
                .statusCode(500)
                .contentType("application/json")
                .body("{\"error\":\"Internal Server Error\",\"message\":\"An error occurred while processing the request\"}")
                .build();
    }

    /**
     * Mock响应类
     */
    @Data
    @Builder
    public static class MockResponse {
        private int statusCode;
        private String contentType;
        private String body;
        private Map<String, String> headers;

        public MockResponse() {}

        public MockResponse(int statusCode, String contentType, String body) {
            this.statusCode = statusCode;
            this.contentType = contentType;
            this.body = body;
        }

        public MockResponse(int statusCode, String contentType, String body, Map<String, String> headers) {
            this.statusCode = statusCode;
            this.contentType = contentType;
            this.body = body;
            this.headers = headers;
        }
    }
} 